<!doctype html>
<html lang="en">

<head>
	<title>A*寻路算法(threeJS)</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<link rel=stylesheet href="css/base.css" />
	<link rel="stylesheet" href="iconfont/iconfont.css">
	<style>
		/* body{
			height: 100%;
		} */
		#inset {
			width: 200px;
			height: 200px;
			background-color: #fff;
			/* or transparent; */
			border: 1px solid black;
			/* or none; */
			margin: 20px;
			padding: 0px;
			position: absolute;
			right: 0px;
			top: 0px;
			z-index: 100;
		}

		#csvFileInput {
			position: absolute;
			left: 0px;
			opacity: 0;
			top: 0px;
			z-index: 100;
		}

		#ThreeJS{
			/* position: absolute;  */
			/* left:0px;  */
			/* top:0px; */
		}		
		
		#btn{
			/* position: absolute;  */
		}

		.myclass{
			display: flex;
			flex-flow: column nowrap;
		}

		.btns{
			display: flex;
			flex-flow: row nowrap ;
			justify-content:space-around;
			align-items:center;

		}

		.color-ditu{
			color: blue;
		}
		.pos-ditu{
			position: absolute;
			left: 90%;
		}
		.mid-pos{
			position: relative;
		}
	</style>

</head>

<body>

	<script src="./three.module.js"></script>
	<script type="text/javascript" src="js/astar.js"></script>
	<script src="js/jquery-1.9.1.js"></script>
	<script src="js/jquery-ui.js"></script>
	<script src="js/Mapbox3DTiles.js"></script>

	<link rel=stylesheet href="css/jquery-ui.css" />
	<div class="myclass">

		<div id="ThreeJS" >

		</div>
		<button type="button" id="btn" onclick="toggleIgnore()" style="position: absolute; z-index: 100; left: 100px", >Reset!</button>
		<div class="btns">
		<span class="iconfont icon-shouye color-ditu" ></span>

		<div class="mid-pos">
			<input type="text" placeholder="搜索..">
			<span class="iconfont icon-ditu color-ditu pos-ditu" ></span>

		</div>

		<span class="iconfont icon-zhongzhi color-ditu" onclick="initCamera()"></span>
		</div>
	</div>

	

	<!-- <div id="inset"></div> -->
	<script src="./stats.module.js"></script>
	<script src="./OrbitControls.js"></script>

	<script>

		// import Stats from './stats.module.js';
		// import * from './three.module.js';
		// import { GUI } from './jsm/libs/dat.gui.module.js';

		// import { OrbitControls } from './OrbitControls.js';



		// MAIN

		// standard global variables
		var container, scene, camera, renderer, controls, stats, container2, scene2, camera2, renderer2;
		var reslutArray = new Array();
		var ignore = false;
		//var keyboard = new THREEx.KeyboardState();
		var graph = [];
		var bridge, ridge;
		// custom global variables
		// var width = 200;
		// var height = 100;
		var length = 1000;
		var flex = 2;
		var maps;

		var girdCellWidth = 1;
		var halfGirdCellWidth = girdCellWidth / 2;
		var sphereRadius = 10

		ajax({ url: "./finalCloudg.bt.csv", type: "json" }).then((data) => {
			graph = data;
			console.log(graph);
			maps = new Graph(graph, { "diagonal": true, "ignore": ignore })


			for (var z = 103; z <= 119; z++) {
				for (var x = 205; x <= 214; x++) {
					(maps.grid)[z][x].mycost = 100
				}
			}
		})





		init();
		animate();
		// init();
		// //render();
		// animate();
		// FUNCTIONS


		//103 214 119 205 z111 x210
		var geometry = new THREE.BoxGeometry(10, 1, 16);
		var matarial = new THREE.MeshLambertMaterial({color: 'red', transparent: true, opacity:0.2});
		var cube = new THREE.Mesh(geometry, matarial);
		cube.position.z = 111
		cube.position.x = 210
		cube.position.y = 5
		scene.add(cube);


		function cleanSphere() {
				let child = scene.children;
				for (var i = 0; i < child.length; i++) {
					if (child[i].geometry instanceof THREE.SphereGeometry) {
						scene.remove(child[i]);
						i--;
					}
				}
				isCaculate = false;
				reslutArray = new Array();
				console.log(reslutArray + " clear")

			}
		
		function initCamera() {
			camera.position.set(0, 1000, 0);
			// camera.position.set(graph.length / 2, 300, graph[0].length / 2);
			camera.lookAt(0, 0, 0);
			
			animate();
			cleanSphere()

		}

		function toggleIgnore() {
			ignore = !ignore;
			let element = document.getElementById("btn");
			var str = "跨越模式:"
			if (ignore) {
				str += "开启"
				element.style.color ="green"
			} else {
				str += "关闭"
				element.style.color ="red"
			}
			element.innerText = str;

		}

		function init() {
			scene = new THREE.Scene();

			// SCENE
			// scene = new THREE.Scene();

			// CAMERA
			var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
			SCREEN_HEIGHT *= 0.97

			var VIEW_ANGLE = 90, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
			var raycaster;
			var CANVAS_WIDTH = 200;
			var CANVAS_HEIGHT = 200;
			camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
			camera.position.set(0, 1000, 0);
			// camera.position.set(graph.length / 2, 300, graph[0].length / 2);
			camera.lookAt(0, 0, 0);
			scene.add(camera);
			// camera.lookAt(graph.length / 2, 0, graph[0].length / 2);
			// RENDERER
			renderer = new THREE.WebGLRenderer({ antialias: true });
			console.log(renderer)
			// if (Detector.webgl)
			// else
			// 	renderer = new THREE.CanvasRenderer();
			renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
			container = document.getElementById('ThreeJS');
			container.appendChild(renderer.domElement);
			// EVENTS
			// THREEx.WindowResize(renderer, camera);
			// THREEx.FullScreen.bindKey({ charCode: 'm'.charCodeAt(0) });
			// CONTROLS
			controls = new OrbitControls(camera, renderer.domElement);

			//上下翻转的最大角度(从上往下->越来越大)
			// controls.maxPolarAngle = 1;
        //上下翻转的最小角度
        // controls.minPolarAngle = 0;
			// STATS
			// dom

			stats = new Stats();
			stats.domElement.style.position = 'absolute';
			stats.domElement.style.bottom = '90%';
			stats.domElement.style.zIndex = 100;
			container.appendChild(stats.domElement);
			// LIGHT
			var light = new THREE.PointLight(0x00000);
			light.position.set(-100, 200, 100);
			scene.add(light);
			var ambientLight = new THREE.AmbientLight(0x111111);
			scene.add(ambientLight);
			// initGround();
			function initGround() {
				// lines
				var Colgeometry = new THREE.Geometry();
				Colgeometry.vertices.push(new THREE.Vector3(- length / 2, 0, 0));
				Colgeometry.vertices.push(new THREE.Vector3(length / 2, 0, 0));
				var geometry = new THREE.PlaneGeometry(length, girdCellWidth);
				var material = new THREE.MeshBasicMaterial({ color: 0x808080, side: THREE.DoubleSide });
				var plane = new THREE.Mesh(geometry, material);
				plane.position.set(0, sphereRadius, graph.length * girdCellWidth / 2);
				scene.add(plane);
				var plane = new THREE.Mesh(geometry, material);
				plane.rotation.y = 90 * Math.PI / 180;
				plane.position.set(graph.length * girdCellWidth / 2, sphereRadius, 0);
				scene.add(plane);
				var plane = new THREE.Mesh(geometry, material);
				plane.position.set(0, sphereRadius, -graph.length * girdCellWidth / 2);
				scene.add(plane);
				var plane = new THREE.Mesh(geometry, material);
				plane.rotation.y = 90 * Math.PI / 180;
				plane.position.set(-graph.length * girdCellWidth / 2, sphereRadius, 0);
				scene.add(plane);

				var skyBoxGeometry = new THREE.CubeGeometry(10000, 10000, 10000);
				var skyBoxMaterial = new THREE.MeshBasicMaterial({ color: 0xFFFFFF, side: THREE.BackSide });
				var skyBox = new THREE.Mesh(skyBoxGeometry, skyBoxMaterial);
				scene.add(skyBox);

				scene.fog = new THREE.FogExp2(0xFFFFFF, 0.00025);

			}

			bridge = new Mapbox3DTiles.Layer({
				id: 'bridge',
				url: './Town02/tileset.json',
				// url: './1206/tileset.json',
				// url: './all/tileset.json',

				color: 0xFFFFFF,
				opacity: 0.5,
				pointsize: 0.1
			});
			bridge.onAdd(null, null, camera, scene, renderer);
			ridge = new Mapbox3DTiles.Layer({
				id: 'bridge',
				url: './finalCloudg/tileset.json',
				color: 0x009966,
				// 透明度
				opacity: 0.1,
				pointsize: 0.01
			});

			ridge.onAdd(null, null, camera, scene, renderer);
			var resolution = 1;

			raycaster = new THREE.Raycaster();
			let mouse = new THREE.Vector2();
			function pickupObjects(e) {
				//将鼠标点击位置的屏幕坐标转成threejs中的标准坐标
				var fxl = new THREE.Vector3(0, 1, 0);
				var groundplane = new THREE.Plane(fxl, 0);
				mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
				mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
				console.log(e);
				//从相机发射一条射线，经过鼠标点击位置
				raycaster.setFromCamera(mouse, camera);
				//计算射线相机到的对象，可能有多个对象，因此返回的是一个数组，按离相机远近排列
				var ray = raycaster.ray;
				let intersects = ray.intersectPlane(groundplane);
				let x = Math.round(intersects.x / resolution);
				let z = Math.round(intersects.z / resolution);
				// let z = intersects.z;
				console.log(x + " " + z + " " + intersects.x + " " + intersects.z);
				// if (x < 0 || z < 9 || x > graph.length || z > graph[0].length) {
				// 	return;
				// }
				//   if((Math.abs(x)<=((length-20)/2)&&Math.abs(z)<=(length-20)/2)){
				//   	alert("请在边缘位置选择开始或结束点");
				//   	return;
				//   }  
				var k, m;
				k = x * resolution
				m = z * resolution
				console.log(k + ' ' + m);
				initSphere(k, m);

			}
			var click = false, clickTimeout

			// document.addEventListener('pointerdown', pickupObjects, false);
			// document.addEventListener('pointerdown', (e) => {
				container.addEventListener('pointerdown', (e) => {
				click = true
				clickTimeout = setTimeout(() => { click = false; }, 100)
			}, false);
			// document.addEventListener('pointerup', (e) => {
				container.addEventListener('pointerup', (e) => {
				console.log(e);
				if (clickTimeout != null) {
					clearTimeout(clickTimeout)
				}
				if (click) {
					pickupObjects(event)
				}
				click = false
			}, false);
			// document.addEventListener('pointerdown', pickupObjects, false);
			var isCaculate = false;
	

			function initSphere(x, z) {
				if (isCaculate) {
					cleanSphere();
				}
				if (reslutArray.length > 0 && reslutArray[0].position.x == x && reslutArray[0].position.z == z) {
					return
				}
					var geometry = new THREE.SphereGeometry(resolution, 32, 32);
					var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
					var sphere = new THREE.Mesh(geometry, material);
					sphere.position.x = x;
					sphere.position.y = resolution;
					sphere.position.z = z;
					sphere.name = "sphere" + reslutArray.length;
					reslutArray.push(sphere);
					scene.add(sphere);

					// var geometry = new THREE.SphereGeometry(resolution, 32, 32);
					// var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
					// var sphere = new THREE.Mesh(geometry, material);
					// sphere.position.x = x;
					// sphere.position.y = resolution;
					// sphere.position.z = z;
					// sphere.name = "sphere1";
					// reslutArray.push(sphere);
					// scene.add(sphere);
					caculatePath(reslutArray);
					// isCaculate = true;
					// reslutArray = new Array();
				// }
				//console.log(reslutArray);

			}

			function caculatePath(resultArray) {
				//console.log(resultArray);
				if (resultArray.length < 2) {
					return
				}
				
				let len = resultArray.length

				var startX = resultArray[len-2].position.z / resolution;
				var startY = resultArray[len-2].position.x / resolution;
				var endX = resultArray[len-1].position.z / resolution;
				var endY = resultArray[len-1].position.x / resolution;
				startX = Math.round(startX)
				startY = Math.round(startY)
				endX = Math.round(endX)
				endY = Math.round(endY)
				// var startY = (resultArray[0].position.x - sphereRadius + graph[0].length / 2) / girdCellWidth;
				// var endX = (resultArray[1].position.z - sphereRadius + graph.length / 2) / girdCellWidth;
				// var endY = (resultArray[1].position.x - sphereRadius + graph[0].length / 2) / girdCellWidth;
				console.log(resultArray);
				console.log(startX + ' ' + startY + ' ' + endX + ' ' + endY);
				if (startX < 0 || startY < 0 || endX < 0 || endY < 0 || startX > graph.length || endX > graph.length || startY > graph[0].length || endY > graph[0].length) {
					alert("无可到达路径，无效点");
					cleanSphere();
					return;
				}
				var start = maps.grid[startX][startY];
				var end = maps.grid[endX][endY];
				var result = astar.search(maps, start, end, {"ignore":ignore});
				var resultIgnore = astar.search(maps, start, end, {"ignore":true});

				console.log(reslutArray + " " + start + " " + end)
				console.log(result)
				if (result.length == 0 && resultIgnore.length == 0) {
					alert("无可到达路径");
					cleanSphere();
					return;
				}

				var drawResult = function (re, color) {
					var timesRun = 0;
					if (!re || re.length <= 0) {
						return
					}
					var interval = setInterval(function () {
						var geometry = new THREE.SphereGeometry(resolution, 32, 32);
						var material = new THREE.MeshBasicMaterial({ color: color || 0xffff00 });
						var sphere = new THREE.Mesh(geometry, material);
						sphere.position.x = re[timesRun].y * resolution;
						sphere.position.y = 2 * resolution;
						sphere.position.z = re[timesRun].x * resolution;
						scene.add(sphere);
						timesRun += 1;
						if (timesRun == re.length) {
							clearInterval(interval);
						}
					}, 1);
				}
				
				drawResult(result, 0xffffff)
				drawResult(resultIgnore, 0x00ffff)
				
				// if (resultIgnore.length > 0) {
				// 	var interval = setInterval(function () {
				// 		var geometry = new THREE.SphereGeometry(resolution, 32, 32);
				// 		var material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
				// 		var sphere = new THREE.Mesh(geometry, material);
				// 		sphere.position.x = result[timesRun].y * resolution;
				// 		sphere.position.y = 2 * resolution;
				// 		sphere.position.z = result[timesRun].x * resolution;
				// 		scene.add(sphere);
				// 		timesRun += 1;
				// 		if (timesRun == result.length) {
				// 			clearInterval(interval);
				// 		}
				// 	}, 1);
				// }




			}


		}

		function animate() {
			requestAnimationFrame(animate);
			bridge.render();
			ridge.render();
			// renderer.render()
			controls.update();
			stats.update();
		}

	</script>

</body>

</html>